#pragma once

#include<mysql/mysql.h>
#include<vector>
#include<string>
#include<iostream>
#include<jsoncpp/json/json.h>
#include<mutex>

using std::vector;
using std::string;
using std::cout;
using std::endl;

#define HOST "119.91.210.136"           
#define USER "gyj"          
#define PASSWORD "gyj008494."           
#define DB "ChatSystem"    
#define DBPORT 3306

class DataBaseSvr
{
    public:
        DataBaseSvr()
        {
            mysql_ = nullptr;
        }

        ~DataBaseSvr()
        {
            if(mysql_ != nullptr)
            {
                mysql_close(mysql_);
            }
        }
        /*
         * 初始化MySQL操作句柄
         * 连接后台服务端
         * 设置字符集
         * */
        bool MysqlInit()
        {
            mysql_ = mysql_init(NULL);
            if(nullptr == mysql_)
            {
                cout << "mysql init failed!" << endl;
                return false;
            }
            MYSQL* ret = mysql_real_connect(mysql_, HOST, USER, PASSWORD, DB, DBPORT, NULL, 0);
            if(NULL == ret)
            {
                cout << "mysql connect failed" << endl;
                mysql_close(mysql_);
                return false;
            }

            mysql_set_character_set(mysql_, "utf8");

            return true;
        }

        /*
         * 获取所用用户的信息，供用户管理模块使用
         * 采用json数据结构保存数据，以出参的方式返回给被调用者
         * */
        bool GetAllUser(Json::Value* all_user)
        {
#define GETALLUSER "select * from user;"

            lock_.lock();
            if(MysqlQuery(GETALLUSER) == false)
            {
                lock_.unlock();
                return false;
            }
            //获取结果集
            MYSQL_RES* res = mysql_store_result(mysql_);
            if(NULL == res)
            {
                lock_.unlock();
                return false;
            }

            lock_.unlock();
            //读取数据
            int row_nums = mysql_num_rows(res);
            for(int i = 0; i < row_nums; i++)
            {
                MYSQL_ROW row = mysql_fetch_row(res);
                //将读取到的一行数据以json的数据各式保存
                Json::Value tmp;
                tmp["userid"] = atoi(row[0]);
                tmp["nickname"] = row[1];
                tmp["school"] = row[2];
                tmp["telnum"] = row[3];
                tmp["passwd"] = row[4];
                all_user->append(tmp);
            }
            return true;
        }

        /*
         * 获取单个用户的好友信息,在程序初始化阶段，让用户管理模块管理起来
         * userid:获取userid对应的好友信息
         * f_id:出参，保存好友信息
         * */
        bool GetFriend(int userid, vector<int>* f_id)
        {
#define GETFRIEND "select friend from friendInfo where userid = '%d';"
            char sql[1024] = {0};
            sprintf(sql, GETFRIEND, userid);

            lock_.lock();
            //执行SQL语句
            if(MysqlQuery(sql) == false)
            {
                lock_.unlock();
                return false;
            }
            //获取结果集
            MYSQL_RES * res = mysql_store_result(mysql_);
            if(res == NULL)
            {
                lock_.unlock();
                return false;
            }
            lock_.unlock();
            //获取数据
            int row_nums = mysql_num_rows(res);
            for(int i = 0; i < row_nums; i++)
            {
                MYSQL_ROW row = mysql_fetch_row(res);
                f_id->push_back(atoi(row[0]));
            }

            //释放结果集
            mysql_free_result(res);
            return true;
        }


        /*
         * 插入注册用户信息
         * */
        bool InsertUser(int userid, const string& nickname, const string& school, 
                        const string& telnum, const string& passwd)
        {
#define INSERTUSER "insert into user(userid, nickname, school, telnum, passwd) values('%d', '%s', '%s','%s', '%s');"
            char sql[1024] = {0};
            sprintf(sql, INSERTUSER, userid, nickname.c_str(), school.c_str(), telnum.c_str(), passwd.c_str());
            //执行SQL语句
            if(MysqlQuery(sql) == false)
            {
                return false;
            }
            return true;
        }

        /*
         * 添加好友时，需要更新数据库表friend
         * */
        bool InsertFriend(int userid1, int userid2)
        {
#define INSERTFRIEND "insert into friendInfo values('%d', '%d');"
            char sql[1024] = {0};
            sprintf(sql, INSERTFRIEND, userid1, userid2);
            //执行SQL语句
            if(MysqlQuery(sql) == false)
            {
                return false;
            }
            return true;
        }
    private:
        /*
         * 由于上述的方法均需要调用数据库进行操作，
         * 因此将其提取出来进行封装
         * */
        bool MysqlQuery(const string& sql)
        {
            if(mysql_query(mysql_, sql.c_str()) != 0)
            {
                cout << "exec failed sql:" << sql << endl;
                return false;
            }
            return true;
        }
    private:
        MYSQL* mysql_;
        std::mutex lock_;
};
